//
//  PieChart.swift
//  HuaYun
//
//  Created by enghou on 2018/7/19.
//  Copyright © 2018年 xyxorigation. All rights reserved.
//

import UIKit

import GLKit

import CoreGraphics


extension CGPoint{
    
    var distance: CGFloat{
        get{
            return CGFloat(sqrtf(Float(x * x + y * y)))
        }
    }
    
    static func -(left: CGPoint,right: CGPoint)->CGPoint{
        return CGPoint(x: left.x - right.x, y: left.y - right.y)
    }
    
}

typealias Area = (CGPoint)->Bool

func circle(radius: CGFloat,center: CGPoint)->Area{
    return {(point) in
        return (point - center).distance <= radius
    }
}

func reverse(area: @escaping Area) -> Area {
    
    return {(point) in
        return !area(point)
    }
}

func minus(mainArea: @escaping Area,notInterest: @escaping Area) -> Area {
    return {(point) in
        return mainArea(point) && reverse(area: notInterest)(point)
    }
}

func sector(begin: CGFloat,end: CGFloat,center: CGPoint,radius: CGFloat) -> Area {
    
    return {(point) in
        
        let beginVector = GLKVector2Normalize(GLKVector2.init(v: (Float(radius * sin(begin)),Float(radius * cos(begin)))))
        
        let endVector = GLKVector2Normalize(GLKVector2.init(v: (Float(radius * sin(end)),Float(radius * cos(end)))))
        
        let currentVector = GLKVector2Normalize(GLKVector2.init(v: ((Float(point.x - center.x)),(Float(point.y - center.y)))))
        
        let angle = GLKVector2DotProduct(beginVector, endVector)
        
        let currentAngle = GLKVector2DotProduct(beginVector, currentVector)
        
        if angle * currentAngle < 0 {
            
            return false
            
        }
        
        return (point - center).distance < radius && (fabsf(currentAngle) < fabsf(angle))
    }
    
}

struct PieChartDataItem {
    
    var color: UIColor = UIColor.clear
    
    var value: CGFloat = 0.0
    
    var title: String = ""
    
}

protocol PieChartDataSource {
    
    var source: Array<PieChartDataItem>{get set}
    
    func click(layer: CAShapeLayer,at index: Int) -> Void
    
}

class PieChart: UIView {
    
    private var _dataSource: [PieChartDataItem] = []
    
    private var layers:Array<CAShapeLayer> = []
    
    private var areas: Array<Area> = []
    
    
    var dataSource: [PieChartDataItem]{
        get{
            return _dataSource
        }
        set{
            _dataSource = newValue
            
            if let totalSubLayers = self.layer.sublayers {
                
                for item in totalSubLayers {
                    
                    item.removeFromSuperlayer()
                    
                }
                
            }
            
            layers.removeAll()
            
            for i in 0 ..< _dataSource.count {
                
                let shape = CAShapeLayer()
                
                shape.fillColor = _dataSource[i].color.cgColor
                
                layers.append(shape)
                
                self.layer.addSublayer(shape)
                
            }
            
            self.setNeedsLayout()
        }
    }
    
    func act(index: Int) -> Void {
        
    }
    
//    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//
//        let touch = touches.first
//
//        if let point = touch?.location(in: self) {
//
//            for fun in self.areas {
//
//                if fun(point) == true {
//
//                }
//
//            }
//
//        }
//
//    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        if self.dataSource.count > 0 {
            
            var total: CGFloat = 0
            
            for item in self.dataSource {
                
                total += item.value
                
            }//计算出总计的数值
            
            for i in 0 ..< self.dataSource.count {
                
                var totalPrevious: CGFloat = 0.0
                
                for j in 0 ..< i {
                    
                    totalPrevious += self.dataSource[j].value
                    
                }
                
                let startAngle = CGFloat.pi * 2 * totalPrevious / total - CGFloat.pi / 2
                
                let deltAngle = CGFloat.pi * 2 * self.dataSource[i].value / total
                
                //可以算出区域了
                areas.append(sector(begin: startAngle, end: startAngle + deltAngle, center: CGPoint(x: self.width / 2, y: self.height / 2), radius: self.width / 2))
                
                let path = UIBezierPath()
                
                path.move(to: CGPoint(x: self.width / 2, y: self.height / 2))
                //
                let firstPoint = CGPoint(x: self.width / 2 + self.width / 2 * sin(startAngle + CGFloat.pi / 2), y: self.height / 2 - self.height / 2 * cos(startAngle + CGFloat.pi / 2))
                //
                path.addLine(to: firstPoint)
                
                path.addArc(withCenter: CGPoint(x: self.width / 2, y: self.height / 2), radius: self.width / 2, startAngle: startAngle, endAngle: startAngle + deltAngle , clockwise: true)
                
                let lineAngle = startAngle + deltAngle * 0.5
                
                let x = self.width / 2 * sin(lineAngle)
                
                let y = self.height / 2 - cos(lineAngle)
                
                path.move(to: CGPoint(x: x, y: y))
                
                let targetX = x + 10 * cos(CGFloat.pi * 0.5 - lineAngle)
                
                let targetY = y - 10 * sin(CGFloat.pi * 0.5 - lineAngle)
                
                path.addLine(to: CGPoint(x: targetX, y: targetY))
                
                if lineAngle < CGFloat.pi {
                                    //+
                    path.addLine(to: CGPoint(x: targetX + 10, y: targetY - 10 * sin(CGFloat.pi * 0.5 - lineAngle)))
                                    //字写在右边
                    let textLayer = CATextLayer()

                    self.layers[i].addSublayer(textLayer)

                    textLayer.contentsScale = UIScreen.main.scale

                    let font = UIFont.systemFont(ofSize: 12)

                    let fontName = font.fontName as CFString

                    let fontRef = CGFont.init(fontName)

                    textLayer.font = fontRef

                    textLayer.fontSize = font.pointSize

                    textLayer.alignmentMode = CATextLayerAlignmentMode.justified

                    textLayer.contents = self.dataSource[i].title

                    let size = self.dataSource[i].title.size(with: font)

                    textLayer.frame = CGRect.init(origin: CGPoint(x: targetX + 10 + 2, y: targetY - 10 * sin(CGFloat.pi * 0.5 - lineAngle) - size.height / 2), size: size)

                } else {
                    path.addLine(to: CGPoint(x: x + 10 * cos(CGFloat.pi * 0.5 - lineAngle) - 10, y: y - 10 * sin(CGFloat.pi * 0.5 - lineAngle)))

                    let textLayer = CATextLayer()

                    self.layers[i].addSublayer(textLayer)

                    textLayer.contentsScale = UIScreen.main.scale

                    let font = UIFont.systemFont(ofSize: 12)

                    let fontName = font.fontName as CFString

                    let fontRef = CGFont.init(fontName)

                    textLayer.font = fontRef

                    textLayer.fontSize = font.pointSize

                    textLayer.alignmentMode = CATextLayerAlignmentMode.justified

                    textLayer.contents = self.dataSource[i].title

                    let size = self.dataSource[i].title.size(with: font)


                    textLayer.frame = CGRect.init(origin: CGPoint(x: x + 10 * cos(CGFloat.pi * 0.5 - lineAngle) - 10 - 2 - size.width, y: y - 10 * sin(CGFloat.pi * 0.5 - lineAngle) - size.height / 2), size: size)
                }
                self.layers[i].path = path.cgPath
                
                self.layers[i].frame = self.frame
            }
        }
    }
    
    func prepare() -> Void {
        //开始绘图前调用
    }
    
    func redraw() -> Void {
        
    }
    
    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

}
